#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <fcntl.h>

#define BUFFER_SIZE 80

void run_command(const char *command);
void split_command(const char *command, char *args[]);
int contains_redirect(const char *command);
int contains_pipe(const char *command);
void process_redirect(const char *command);
void process_pipe(const char *command);

int main() {
    char command[BUFFER_SIZE];
    while (1) {
        printf(">> ");
        if (fgets(command, BUFFER_SIZE, stdin) == NULL) {
            break;
        }
        command[strcspn(command, "\n")] = '\0'; // Remove newline character
        if (strcmp(command, "exit") == 0 || strcmp(command, "logout") == 0) {
            break;
        }
        run_command(command);
    }
    return 0;
}

void run_command(const char *command) {
    if (contains_redirect(command)) {
        process_redirect(command);
    } else if (contains_pipe(command)) {
        process_pipe(command);
    } else {
        char *args[BUFFER_SIZE / 2 + 1];
        split_command(command, args);
        if (args[0] == NULL) {
            return;
        }
        pid_t pid = fork();
        if (pid < 0) {
            perror("fork failed");
        } else if (pid == 0) {
            // Child process
            if (execvp(args[0], args) < 0) {
                perror("execvp failed");
                exit(1);
            }
        } else {
            // Parent process
            wait(NULL);
        }
    }
}

void split_command(const char *command, char *args[]) {
    int index = 0;
    char *token = strtok((char *)command, " ");
    while (token != NULL) {
        if (strcmp(token, ">") == 0) {
            break; // Stop parsing if redirection is found
        }
        args[index++] = token;
        token = strtok(NULL, " ");
    }
    args[index] = NULL;
}

int contains_redirect(const char *command) {
    return strchr(command, '>') != NULL;
}

void process_redirect(const char *command) {
    char *args[BUFFER_SIZE / 2 + 1];
    char *output_file = NULL;
    int arg_index = 0;
    char *token = strtok((char *)command, " ");
    while (token != NULL) {
        if (strcmp(token, ">") == 0) {
            token = strtok(NULL, " ");
            output_file = token;
            break;
        }
        args[arg_index++] = token;
        token = strtok(NULL, " ");
    }
    args[arg_index] = NULL;

    if (output_file != NULL) {
        int file_descriptor = open(output_file, O_WRONLY | O_CREAT | O_TRUNC, 0644);
        if (file_descriptor < 0) {
            perror("open failed");
            return;
        }
        pid_t pid = fork();
        if (pid < 0) {
            perror("fork failed");
            close(file_descriptor);
            return;
        } else if (pid == 0) {
            // Child process
            dup2(file_descriptor, STDOUT_FILENO);
            close(file_descriptor);
            if (execvp(args[0], args) < 0) {
                perror("execvp failed");
                exit(1);
            }
        } else {
            // Parent process
            close(file_descriptor);
            wait(NULL);
        }
    }
}

int contains_pipe(const char *command) {
    return strchr(command, '|') != NULL;
}

void process_pipe(const char *command) {
    // Placeholder for pipe handling logic
    // This function should be implemented based on the specific requirements
}